package com.hd123.rumba.sql;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import java.util.Vector;

import org.apache.log4j.Logger;

import com.hd123.rumba.runtime.Persistent;
import com.hd123.rumba.util.ObjectUtil;

import net.sf.hibernate.HibernateException;

public abstract class SelectExecutorBase {
  protected Connection connection;
  protected SQLSubquery query;
  protected String exeStatement;
  protected Vector exeParameters;
  protected Logger logger = Logger.getLogger(this.getClass());

  public Vector getExeParameters() {
    return exeParameters;
  }

  public String getExeStatement() {
    return exeStatement;
  }

  public int getCount() throws HibernateException {
    try {
      Date st = new Date();
      String statement = getCountStatement(query);
      exeStatement = statement;
      Vector parameters = query.getParametersVector();
      exeParameters = parameters;
      int rowcount = 0;

      String perfConstruct = Long.toString(new Date().getTime() - st.getTime());
      st = new Date();

      PreparedStatement preparedStatement = null;
      ResultSet resultset = null;
      String perfPrepare = null;
      logger.debug(exeStatement);
      logger.debug(exeParameters);
      try {
        preparedStatement = connection.prepareStatement(statement);
        for (int k = 0; k < parameters.size(); ++k) {
          if (parameters.get(k) instanceof Persistent)
            preparedStatement.setObject(k + 1, ((Persistent) parameters.get(k)).getUuid());
          else
            preparedStatement.setObject(k + 1, parameters.get(k));
        }

        perfPrepare = Long.toString(new Date().getTime() - st.getTime());
        st = new Date();

        try {
          resultset = preparedStatement.executeQuery();
          if (resultset.next())
            rowcount = resultset.getInt(1);
        } catch (SQLException sqlexception) {
          preparedStatement.close();
          preparedStatement = null;
          throw sqlexception;
        }
      } finally {
        if (resultset != null)
          resultset.close();
        if (preparedStatement != null)
          preparedStatement.close();
      }

      String perfExecute = Long.toString(new Date().getTime() - st.getTime());
      logger.debug("count: " + perfConstruct + "|" + perfPrepare + "|" + perfExecute);
      return rowcount;
    } catch (Exception e) {
      logger.error(ObjectUtil.getErrorTrace(e));
      throw new HibernateException(e);
    }
  }

  /**
   * Should be override by subclass to generate the correct SQL statement
   * 
   * @param query
   * @return
   */
  protected abstract String getCountStatement(SQLSubquery query) throws Exception;
//  {
//    return query.getCountStatement();
//  }

}
